/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_zml.htm
 *
 * Zhiqim Zml is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.zml.statement;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.zhiqim.kernel.Global;
import org.zhiqim.kernel.util.Arrays;
import org.zhiqim.kernel.util.Classes;
import org.zhiqim.kernel.util.Strings;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.zml.Expression;
import org.zhiqim.zml.ExpressionParser;
import org.zhiqim.zml.Statement;
import org.zhiqim.zml.ZmlVariable;
import org.zhiqim.zml.exception.ExpressionException;
import org.zhiqim.zml.exception.StatementException;

/**
 * 包含语句，格式为：<#interceptor "chkLogin,chkAdmin"/><br>
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
public class _Interceptor extends Statement
{
    private Expression expression;
    
    @Override
    public boolean isNesting()
    {
        return false;
    }
    
    @Override
    public void parseStatement() throws StatementException
    {
        String s = Strings.trim(getStatement(), INTERCEPTOR_BEGIN, INTERCEPTOR_END);
        if (Validates.isEmptyBlank(s))
            throw new StatementException(this, INTERCEPTOR + "未配置被包含的文件路径");
        
        try
        {
            expression = ExpressionParser.parseExpression(s);
        }
        catch (ExpressionException e)
        {
            throw new StatementException(this, INTERCEPTOR + e.getMessage());
        }
    }

    @Override
    public String process(ZmlVariable variableMap) throws StatementException
    {
        Object request = variableMap.get("request");
        Object response = variableMap.get("response");
        if (request == null || response == null)
            throw new StatementException(this, INTERCEPTOR + "[request或response]变量不存在，不支持拦截器");
        
        try
        {
            //查询响应提供方法
            Method isResponseSuccess = Classes.getMethodDeep(request.getClass(), "isResponseSuccess");
            Method isCommitted = Classes.getMethodDeep(response.getClass(), "isCommitted");
            
            String interceptors = String.valueOf(expression.build(variableMap));
            String[] interceptorArr = Arrays.toStringArray(interceptors);
            for (String interceptor : interceptorArr)
            {
                //1.找拦截器类
                Class<?> interceptorClass = Global.forName(interceptor);
                if (interceptorClass == null)
                    throw new StatementException(this, INTERCEPTOR + "配置的拦截器["+interceptor+"]不正确");
                
                //2.找拦截器方法
                Method method = null;
                for (Method m : interceptorClass.getDeclaredMethods())
                {
                    //2.1方法名为intercept
                    if (!"intercept".equals(m.getName()))
                        continue;
                    
                    //2.2参数是1个
                    Class<?>[] paramTypes = m.getParameterTypes();
                    if (paramTypes == null || paramTypes.length != 1)
                        continue;
                    
                    //2.3参数是request类或父类
                    Class<?> paramType = paramTypes[0];
                    if (Classes.isImplement(request.getClass(), paramType) || request.getClass().isAssignableFrom(paramType))
                    {
                        method = m;
                        break;
                    }
                }
                
                if (method == null)
                    throw new StatementException(this, INTERCEPTOR + "配置的拦截器没有intercept(request)方法");
                
                //3.执行拦截器
                Object obj = Global.getc(interceptorClass);
                method.invoke(obj, request);
                
                //4.判断是否响应提交了
                if ((Boolean)isCommitted.invoke(response))
                {//已被拦截器提交不再作后续的语句处理
                    throw new _Return.ReturnException();
                }
                
                if (!(Boolean)isResponseSuccess.invoke(request))
                {//已被拦截器跳转不再作后续的语句处理
                    throw new _Return.ReturnException();
                }
            }
            
            //仅执行不返回文本
            return null;
        }
        catch (_Return.ReturnException e)
        {//当返回值一样直接抛出
            throw e;
        }
        catch (Exception e)
        {//其他认为是异常
            if (e instanceof InvocationTargetException)
                throw new StatementException(this, INTERCEPTOR + ((InvocationTargetException)e).getTargetException().getMessage());
            else if (e.getCause() != null)
                throw new StatementException(this, INTERCEPTOR + e.getCause().getMessage());
            else
                throw new StatementException(this, INTERCEPTOR + e.getMessage());
        }
    }
}
